﻿using Azure;
using EFCore.BulkExtensions;
using Furion;
using Furion.DatabaseAccessor;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.RemoteRequest.Extensions;
using Furion.UnifyResult;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using OfficeOpenXml;
using Serilog;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using TencentCloud.Mongodb.V20190725.Models;
using TulingMember.Application.Dto;
using TulingMember.Core;
using Yitter.IdGenerator;

namespace TulingMember.Application
{
    [ApiDescriptionSettings("入库单")]
    public class PurchaseOrderService : IDynamicApiController
    {
        private readonly ILogger _logger;
        private readonly IRepository<cts_Supplier> _supplierRepository;
        private readonly IRepository<cts_SupplierPayLog> _supplierpaylogRepository;
        private readonly IRepository<cts_PurchaseOrder> _purchaseorderRepository;
        private readonly IRepository<cts_PurchaseOrderDetail> _purchaseorderdetailRepository;
        private readonly IRepository<cts_PrintTag> _printtagRepository;
        private readonly IRepository<cts_Product> _productRepository;
        private readonly IRepository<cts_ProductLog> _productlogRepository;
        private readonly IRepository<cts_ProductType> _ProductType;
        public PurchaseOrderService(ILogger logger
            , IRepository<cts_Supplier> supplierRepository
            , IRepository<cts_SupplierPayLog> supplierpaylogRepository
            , IRepository<cts_PurchaseOrder> purchaseorderRepository
            , IRepository<cts_PurchaseOrderDetail> purchaseorderdetailRepository
            , IRepository<cts_PrintTag> printtagRepository
            , IRepository<cts_Product> productRepository
            , IRepository<cts_ProductLog> productlogRepository
            , IRepository<cts_ProductType> productType)
        {
            _logger = logger;
            _supplierRepository = supplierRepository;
            _supplierpaylogRepository = supplierpaylogRepository;
            _purchaseorderRepository = purchaseorderRepository;
            _purchaseorderdetailRepository = purchaseorderdetailRepository;
            _printtagRepository = printtagRepository;
            _productRepository = productRepository;
            _productlogRepository = productlogRepository;
            _ProductType = productType;
        }

        private static long SupplierCode = App.GetConfig<long>("Supplier:SupplierCode");
        private static string SupplierName = App.GetConfig<string>("Supplier:SupplierName");
        #region 入库单
        /// <summary>
        /// 列表
        /// </summary> 
        public PagedList<cts_PurchaseOrder> SearchPurchaseOrder(BaseInput input)
        {

            var search = _purchaseorderRepository.AsQueryable();
            if (!string.IsNullOrEmpty(input.keyword))
            {
                search = search.Where(m => m.SupplierName.Contains(input.keyword)
                 || m.OrderDesc.Contains(input.keyword));
            }
            if (input.sdate != null)
            {
                search = search.Where(m => m.CreatedTime >= input.sdate);
            }
            if (input.edate != null)
            {
                var edate = input.edate?.AddDays(1).Date;
                search = search.Where(m => m.CreatedTime < edate);
            }
            if (input.supplierid > 0)
            {
                search = search.Where(m => m.SupplierId == input.supplierid);
            }
            var amount = search.GroupBy(m => 1).Select(m => new
            {
                Amount = m.Sum(m => m.Amount),
                FreightFee = m.Sum(m => m.FreightFee),
                EditionFee = m.Sum(m => m.EditionFee),
                GiveupFee = m.Sum(m => m.GiveupFee),
                AllFee = m.Sum(m => m.AllFee),
                PayFee = m.Sum(m => m.PayFee)
            }).FirstOrDefault();
            search = search.OrderByDescending(m => m.OrderDate).OrderByDescending(m => m.OrderNo);
            var data = search.ToPagedList(input.page, input.size);
            UnifyContext.Fill(amount);
            return data;
        }
        /// <summary>
        /// 获取入库单
        /// </summary> 

        public PurchaseOrderDto GetPurchaseOrder(long id)
        {
            var order = _purchaseorderRepository.FindOrDefault(id);
            var detail = _purchaseorderdetailRepository.Where(m => m.PurchaseOrderId == id).ToList();
            var printtag = _printtagRepository.Where(m => m.IsShow == 1).ToList();
            return new PurchaseOrderDto
            {
                printtag = printtag,
                order = order,
                detail = detail
            };
        }

        /// <summary>
        /// 获取产品入库记录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public PagedList<cts_PurchaseOrderDetail> SearchProductPurchaseDetail(BaseInput input)
        {
            var search = _purchaseorderdetailRepository.Where(m => m.ProductId == input.productid).AsQueryable();
            search = search.OrderByDescending(m => m.CreatedTime);
            return search.ToPagedList(input.page, input.size);
        }

        /// <summary>
        /// 药品入库导入
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        [SecurityDefine("purchaseorder")]
        [HttpPost]
        public List<cts_PurchaseOrderDetail> ImportExcel([FromForm(Name = "file")] IFormFile file)
        {
            if (file == null || file.Length <= 0 || file.FileName.IndexOf(".xls") <= 0) throw Oops.Bah("请选择EXCEL模板").StatusCode(ErrorStatus.ValidationFaild);
            var list = new List<cts_PurchaseOrderDetail>();
            IWorkbook workbook = null;
            ISheet sheet = null;
            workbook = new XSSFWorkbook(file.OpenReadStream());
            sheet = workbook.GetSheetAt(0);
            IRow headerRow = sheet.GetRow(0);
            int cellCount = headerRow.LastCellNum;
            for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
            {
                try
                {
                    IRow row = sheet.GetRow(i);
                    if (row == null) continue;
                    if (row.Cells.All(d => d.CellType == CellType.Blank)) continue;
                    string productName = string.Empty;
                    string Formulations = string.Empty;
                    string Specification = string.Empty;
                    decimal Price = 0;
                    if (row.GetCell(0).CellType == CellType.String) productName = row.GetCell(0).StringCellValue;
                    if (row.GetCell(3).CellType == CellType.String) Formulations = row.GetCell(3).StringCellValue;
                    if (row.GetCell(4).CellType == CellType.String) Specification = row.GetCell(4).StringCellValue;
                    if (row.GetCell(9).CellType == CellType.Numeric) Price = (decimal)row.GetCell(9).NumericCellValue;
                    if (string.IsNullOrEmpty(productName) || string.IsNullOrEmpty(Formulations) || string.IsNullOrEmpty(Specification) || Price == 0) continue;
                    cts_PurchaseOrderDetail purchaseOrderDetail = new cts_PurchaseOrderDetail();
                    purchaseOrderDetail.ProductName = productName;
                    purchaseOrderDetail.Unit = row.GetCell(7).StringCellValue;
                    purchaseOrderDetail.Specification = Specification;
                    purchaseOrderDetail.Num = row.GetCell(8).CellType == CellType.Numeric ? (int)row.GetCell(8).NumericCellValue : 0;
                    purchaseOrderDetail.Price = Price;
                    purchaseOrderDetail.Remark = row.GetCell(11).StringCellValue;
                    purchaseOrderDetail.GuoyaoZhunzi = row.GetCell(2).StringCellValue;
                    purchaseOrderDetail.Manufacturer = row.GetCell(1).StringCellValue;
                    purchaseOrderDetail.Formulations = Formulations;
                    if (row.GetCell(5).CellType == CellType.Numeric && DateUtil.IsCellDateFormatted(row.GetCell(5)))
                    {
                        purchaseOrderDetail.ManufacturingDate = Convert.ToDateTime(row.GetCell(5).DateCellValue);
                    }
                    else
                    {
                        purchaseOrderDetail.ManufacturingDate = null;
                    }
                    if (row.GetCell(6).CellType == CellType.Numeric && DateUtil.IsCellDateFormatted(row.GetCell(6)))
                    {
                        purchaseOrderDetail.ExpirationDate = Convert.ToDateTime(row.GetCell(6).DateCellValue);
                    }
                    else
                    {
                        purchaseOrderDetail.ExpirationDate = null;
                    }
                    //purchaseOrderDetail.ManufacturingDate = DateUtil.IsCellDateFormatted(row.GetCell(5)) ? null : row.GetCell(5).DateCellValue;
                    //purchaseOrderDetail.ExpirationDate = DateUtil.IsCellDateFormatted(row.GetCell(6)) ? null : row.GetCell(6).DateCellValue;
                    purchaseOrderDetail.ProductId = 0;
                    purchaseOrderDetail.Num = purchaseOrderDetail.Num < 0 ? 0 : purchaseOrderDetail.Num;
                    purchaseOrderDetail.Price = purchaseOrderDetail.Price < 0 ? 0 : purchaseOrderDetail.Price;
                    purchaseOrderDetail.Amount = purchaseOrderDetail.Price * purchaseOrderDetail.Num;
                    cts_PurchaseOrderDetail detail = list.Find(x => x.ProductName == purchaseOrderDetail.ProductName && x.Formulations == purchaseOrderDetail.Formulations && x.Specification == purchaseOrderDetail.Specification && x.Price == purchaseOrderDetail.Price && x.ExpirationDate == purchaseOrderDetail.ExpirationDate);
                    if (detail != null && !string.IsNullOrEmpty(detail.ProductName))
                    {
                        detail.Num += purchaseOrderDetail.Num;
                    }
                    else
                    {
                        list.Add(purchaseOrderDetail);
                    }
                }
                catch (Exception ex)
                {
                    continue;
                }

            }
            return list;
        }

        /// <summary>
        /// 获取入库单打印
        /// </summary> 

        public PurchaseOrderDto GetPurchaseOrderAndPrint(long id)
        {

            var order = _purchaseorderRepository.FindOrDefault(id);
            var detail = _purchaseorderdetailRepository.Where(m => m.PurchaseOrderId == id).ToList();
            var printtag = _printtagRepository.Where(m => m.IsShow == 1).ToList();
            //获取系统配置
            var tenantid = App.User.FindFirst(ClaimConst.TENANT_ID).Value;
            cts_SystemConfig systemconfig = new cts_SystemConfig();
            var configKey = AppStr.SystemConfig + "_" + tenantid;
            var systemconfigStr = RedisHelper.GetString(configKey);
            if (!string.IsNullOrEmpty(systemconfigStr))
            {
                systemconfig = systemconfigStr.FromJson<cts_SystemConfig>();
            }
            order.PrintNum += 1;
            return new PurchaseOrderDto
            {
                companyname = systemconfig.configstr1,
                printtag = printtag,
                order = order,
                detail = detail
            };
        }
        /// <summary>
        /// 下载模板
        /// </summary>
        /// <returns></returns>
        [SecurityDefine("purchaseorder")]
        [HttpGet]
        public async Task<IActionResult> DownloadTemplate()
        {
            //存储路径
            var path = Path.Combine(App.HostEnvironment.ContentRootPath, "Templates/");
            //文件路径
            var filePath = Path.Join(path, "DrugImportTemplate" + ".xlsx");
            var fileName = HttpUtility.UrlEncode("药品入库导入模板_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xlsx", Encoding.GetEncoding("UTF-8"));
            return new FileStreamResult(new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite), "application/octet-stream") { FileDownloadName = fileName };
        }

        /// <summary>
        /// 保存入库单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [SecurityDefine("purchaseorder")]
        [UnitOfWork]
        public long SavePurchaseOrder(PurchaseOrderDto dto)
        {
            var order = dto.order;
            var detail = dto.detail;
            var productList = new List<cts_Product>();
            var ProductType = _ProductType.AsQueryable(x => x.ParentId == 0 && !x.IsDeleted).FirstOrDefault();
            //初始化产品ID
            foreach (var item in dto.detail)
            {
                if (item.ProductId == 0)
                {
                    //检查药品是否存在
                    var oldProduct = _productRepository.DetachedEntities.Where(m => m.Name == item.ProductName && m.Formulations == item.Formulations && m.Specification == item.Specification && m.Price == item.Price && m.ExpirationDate == item.ExpirationDate).FirstOrDefault();
                    if (oldProduct == null)
                    {
                        var product = new cts_Product
                        {
                            Id = YitIdHelper.NextId(),
                            Name = item.ProductName,
                            Manufacturer = item.Manufacturer,
                            Specification = item.Specification,
                            Formulations = item.Formulations,
                            Unit = item.Unit,
                            Price = item.Price,
                            TypeId = ProductType.Id,
                            Num = 0,
                            GuoyaoZhunzi = item.GuoyaoZhunzi,
                            ManufacturingDate = item.ManufacturingDate.Value,
                            ExpirationDate = item.ExpirationDate.Value,
                            Description = item.Remark,
                        };
                        productList.Add(product);
                        item.ProductId = product.Id;
                    }
                    else
                    {
                        item.ProductId = oldProduct.Id;
                    }
                }
            }
            var today = DateTime.Now.ToString("yyMMdd");
            var tenantid = App.User.FindFirst(ClaimConst.TENANT_ID).Value;
            //获取系统配置
            cts_SystemConfig systemconfig = new cts_SystemConfig();
            var configKey = AppStr.SystemConfig + "_" + tenantid;
            var systemconfigStr = RedisHelper.GetString(configKey);
            if (!string.IsNullOrEmpty(systemconfigStr))
            {
                systemconfig = systemconfigStr.FromJson<cts_SystemConfig>();
            }
            order.Num = detail.Sum(m => m.Num);
            if (systemconfig.config4 == 1)//保留整数
            {
                order.Amount = detail.Sum(m => Math.Floor(m.Price * m.Num));
                order.AllFee = Math.Floor(order.Amount + order.FreightFee + order.EditionFee - order.GiveupFee);
            }
            else
            {
                order.Amount = Math.Round(detail.Sum(m => Math.Round(m.Price * m.Num, 2, MidpointRounding.AwayFromZero)), 2, MidpointRounding.AwayFromZero);
                order.AllFee = Math.Round(order.Amount + order.FreightFee + order.EditionFee - order.GiveupFee, 2, MidpointRounding.AwayFromZero);
            }
            order.OrderDesc = string.Join(';', detail.Select(m => m.ProductName));
            order.SupplierId = SupplierCode;
            order.SupplierName = SupplierName;
            if (order.Id == 0)
            {
                var redisKey = AppStr.PurchaseOrderNoKey + "_" + tenantid + "_" + today;
                var OrderNoIndex = RedisHelper.StringIncrement(redisKey);
                if (OrderNoIndex == 0)
                {
                    OrderNoIndex = RedisHelper.StringIncrement(redisKey);
                }
                order.Id = YitIdHelper.NextId();
                order.OrderNo = "RK" + today + OrderNoIndex.ToString().PadLeft(3, '0');
                order.Status = 0;
                _purchaseorderRepository.Insert(order);

                foreach (var item in detail)
                {
                    var productName = item.ProductName.Trim();
                    item.PurchaseOrderId = order.Id;
                    item.Id = YitIdHelper.NextId();
                    if (systemconfig.config4 == 1)//保留整数
                    {
                        item.Amount = Math.Floor(item.Price * item.Num);
                    }
                    else
                    {
                        item.Amount = Math.Round(item.Price * item.Num, 2, MidpointRounding.AwayFromZero);
                    }
                }
            }
            else
            {
                var oldOrder = _purchaseorderRepository.DetachedEntities.Where(m => m.Id == order.Id).FirstOrDefault();
                if (oldOrder.Status == 1)
                {
                    throw Oops.Bah("已审核入库单不允许修改").StatusCode(ErrorStatus.ValidationFaild);
                }
                _purchaseorderRepository.UpdateExclude(order, new string[] { nameof(order.PrintNum) });
                _purchaseorderdetailRepository.Where(a => a.PurchaseOrderId == order.Id).BatchDelete();
                foreach (var item in detail)
                {
                    var productName = item.ProductName.Trim();
                    item.PurchaseOrderId = order.Id;
                    item.Id = YitIdHelper.NextId();
                    if (systemconfig.config4 == 1)//保留整数
                    {
                        item.Amount = Math.Floor(item.Price * item.Num);
                    }
                    else
                    {
                        item.Amount = Math.Round(item.Price * item.Num, 2, MidpointRounding.AwayFromZero);
                    }
                }
            }
            if (productList.Count > 0)
            {
                _productRepository.InsertNow(productList);
            }
            _purchaseorderdetailRepository.Insert(detail);
            return order.Id;

        }
        /// <summary>
        /// 删除 
        /// </summary>  
        [SecurityDefine("purchaseorder")]
        public void DeletePurchaseOrder(long id)
        {

            var oldOrder = _purchaseorderRepository.DetachedEntities.Where(m => m.Id == id).FirstOrDefault();
            if (oldOrder.Status == 1)
            {
                throw Oops.Bah("已审核入库单不允许删除").StatusCode(ErrorStatus.ValidationFaild);
            }
            _purchaseorderRepository.FakeDelete(id);
        }
        /// <summary>
        /// 审核、弃审 
        /// </summary>  
        [SecurityDefine("purchaseorder")]
        [UnitOfWork]
        public void CheckPurchaseOrder(CheckDto input)
        {

            var order = _purchaseorderRepository.FindOrDefault(input.Id);
            if (order.Status == input.Status)
            {
                throw Oops.Bah("该单据无需此操作").StatusCode(ErrorStatus.ValidationFaild);
            }
            order.Status = input.Status;
            var orderDetails = _purchaseorderdetailRepository.Where(m => m.PurchaseOrderId == order.Id).ToList();
            var changeAmount = Math.Round(order.PayFee - order.AllFee, 2, MidpointRounding.AwayFromZero);
            if (input.Status == 1)//审核
            {
                //库存数量变更
                foreach (var item in orderDetails)
                {
                    var product = _productRepository.FindOrDefault(item.ProductId);

                    _productlogRepository.Insert(new cts_ProductLog
                    {
                        Id = YitIdHelper.NextId(),
                        ProductId = product.Id,
                        ProductName = product.Name,
                        OldNum = product.Num,
                        ChangeNum = item.Num,
                        NewNum = product.Num + item.Num,
                        TagName = "药品入库",
                        TagType = ProductChangeTag.In,
                        RelationId = order.Id,
                    });
                    product.Num += item.Num;
                }

            }
            else
            { //弃审
              //库存数量变更
                foreach (var item in orderDetails)
                {
                    var product = _productRepository.FindOrDefault(item.ProductId);

                    _productlogRepository.Insert(new cts_ProductLog
                    {
                        Id = YitIdHelper.NextId(),
                        ProductId = product.Id,
                        ProductName = product.Name,
                        OldNum = product.Num,
                        ChangeNum = -item.Num,
                        NewNum = product.Num - item.Num,
                        TagName = "入库单入库弃审",
                        TagType = ProductChangeTag.Out,
                        RelationId = order.Id,
                    });
                    product.Num -= item.Num;
                }
            }
        }
        #endregion

        #region 导出

        #endregion

    }
}
